﻿// Copyright (c) 2013 Bryan C. O'Connell
// http://wsubi.codeplex.com/license
// Purpose: Defines a database query that can be processed by wsubi.

using System;
using System.IO;

namespace Wsubi
{
    class Query
    {
        /// <summary>Initialize a new Query object based in input and get the 
        /// query text from the specified file and location.</summary>
        /// <param name="UserCommand">Command to process. Only 'Query' Commands are accepted.</param>
        /// <param name="QueryFileFolder">Location of the query file.</param>
        public Query(Command UserCommand, string QueryFileFolder) 
        {
            if (UserCommand.CommandType != CommandTypes.Query)
            {
                throw new ArgumentException("CommandType specified was not Query.");
            }
            else
            {
                ParseQueryDetails(UserCommand.Params);                
            }

            if (QueryType != QueryTypes.Invalid)
            {
                string QueryFile = UserCommand.Target;
                GetQueryTextFromFile(QueryFileFolder + QueryFile);
            }
        }

        /// <summary>Breaks the QueryDetails into the 3 segments (QueryType, OutputsTo, ConnectionString) 
        /// known by the Query class. Segments are saved for reference.</summary>
        /// <param name="QueryRequest">Query command parameters to be parsed.</param>
        /// <remarks>Each segment must always be provided or the query is invalid.</remarks>
        private void ParseQueryDetails(string QueryRequest)
        {
            const char SPACE = (char)32;
            char[] Delimiter_Space = new char[] { SPACE };
            string[] QuerySegments = QueryRequest.Split(Delimiter_Space, StringSplitOptions.RemoveEmptyEntries);

            const int MINIMUM_SEGMENTS = 3;

            if (QuerySegments.Length < MINIMUM_SEGMENTS)
            {
                _QueryType = QueryTypes.Invalid;
            }
            else
            {
                _Result = QuerySegments[0];
                _Location = QuerySegments[1];
                _ConnectionString = QueryRequest.Remove(0, (_Result + SPACE + _Location).Length).Trim();

                DetermineQueryType();
                DetermineQueryOutput(); 
            }                                         
        }

        /// <summary>Sets the QueryType based on the object's current Result value.</summary>
        private void DetermineQueryType()
        {
            switch (_Result.ToLower())
            {
                case "value":
                    _QueryType = QueryTypes.Value;
                    break;

                case "row":
                    _QueryType = QueryTypes.Row;
                    break;

                case "rowset":
                    _QueryType = QueryTypes.Rowset;
                    break;

                case "nonquery":
                    _QueryType = QueryTypes.NonQuery;
                    break;

                default:
                    _QueryType = QueryTypes.Invalid;
                    break;
            }
        }

        /// <summary>Sets the QueryOutput based on the object's current Location value.</summary>
        private void DetermineQueryOutput()
        {
            switch (_Location.ToLower())
            {
                case "file":
                    _QueryOutput = OutputsTo.File;
                    break;

                case "screen":
                    _QueryOutput = OutputsTo.Screen;
                    break;

                default:
                    _QueryOutput = OutputsTo.Invalid;
                    break;
            }
        }

        /// <summary>Reads the query file and stores the text.</summary>
        /// <param name="QueryFilepath">Full path to the query file to be read.</param>
        private void GetQueryTextFromFile(string QueryFilepath)
        {
            if (File.Exists(QueryFilepath))
            {
                using (StreamReader Reader = new StreamReader(QueryFilepath))
                {
                    _QueryText = Reader.ReadToEnd();
                }
            }
            else
            {
                throw new FileNotFoundException("The query file specified was not found.");
            }            
        }

        #region Properties

        // Current query text.
        private string _QueryText;
        public string QueryText
        { get { return _QueryText; } }

        // Current query type.
        private QueryTypes _QueryType;
        public QueryTypes QueryType
        { get { return _QueryType; } }

        // String representation of the _QueryType.
        private string _Result;

        // Connection info for the database the current Query is intended to be performed against.
        private string _ConnectionString;
        public string ConnectionString
        { get { return _ConnectionString; } }

        // Current query output type.
        private OutputsTo _QueryOutput;
        public OutputsTo QueryOutput
        { get { return _QueryOutput; } }

        // String representation of the _OutputsTo value.
        private string _Location;

        #endregion
    }
}
